package com.powernode.filter;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.powernode.constant.AuthConstants;
import com.powernode.model.SecurityUser;
import com.powernode.util.RedisCache;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @Author 梁卓
 * @Version 1.0
 * @ClassName TokenTranslationFilter
 * @Description token转换过滤器
 * @Date 2024/07/21 15:22
 */
@Component
public class TokenTranslationFilter extends OncePerRequestFilter {

    @Resource
    private RedisCache redisCache;

    /**
     * token解析过滤器：
     *  只处理携带token的请求，将用户信息转换出来
     *  没有携带token的请求，交给security框架处理，如果放行则直接访问，
     *    如果没有放行，则交给security的AuthenticationEntryPoint处理
     *  1.获取token值
     *  2.如果有，token转换并处理token续约
     *  3.存放到security上下文中
     *
     * @param request 请求
     * @param response 响应
     * @param filterChain 过滤器链
     * @throws ServletException servlet异常
     * @throws IOException IO异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authorization = request.getHeader(AuthConstants.AUTHORIZATION);
        if (StrUtil.isBlankIfStr(authorization)) {
            logger.error("token转换过滤器：authorization为空");
            filterChain.doFilter(request, response);
            return;
        }
        // 获取token
        String token = authorization.replaceFirst(AuthConstants.AUTHORIZATION_PREFIX, "");
        if (StrUtil.isBlankIfStr(token)) {
            logger.error("token转换过滤器：token为空");
            filterChain.doFilter(request, response);
            return;
        }
        SecurityUser securityUser = redisCache.getCacheObject(AuthConstants.LOGIN_TOKEN_PREFIX + token);
        if (ObjectUtil.isNull(securityUser)) {
            logger.error("token转换过滤器：securityUser为空");
            filterChain.doFilter(request, response);
            return;
        }
        // 存放到security上下文中
        SecurityContextHolder.getContext().setAuthentication(
                new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities()));
        // 达到阈值进行--续签
        Long expireTime = redisCache.getExpire(AuthConstants.LOGIN_TOKEN_PREFIX + token);
        if (ObjectUtil.isNull(expireTime) || expireTime < AuthConstants.TOKEN_EXPIRE_THRESHOLD_TIME)  {
            redisCache.expire(AuthConstants.LOGIN_TOKEN_PREFIX + token, AuthConstants.TOKEN_TIME, TimeUnit.SECONDS);
        }
        // 放行
        filterChain.doFilter(request, response);
    }
}
